// Copyright (C) 2006 Taylor L. Riché <riche@cs.utexas.edu>
//  
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software 
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//


#ifndef IP_PACKET_HH
#define IP_PACKET_HH

#include <netinet/ip.h>

#include <lagniappe/RData.h>
#include "Eth_Packet.hh"

namespace pktTypes {

const unsigned int IPv4_HSIZE = 0x14; // 20

class IP_Packet : public Eth_Packet
{
protected:
  iphdr * ipHdr;
  payload_t ip_payload;
  uint16_t ipLength;
public:
  IP_Packet() : ipHdr(NULL), ip_payload(NULL) {}
  IP_Packet(const Eth_Packet & pkt) : Eth_Packet(pkt)
  {
    assert(payload != NULL);
    ipHdr = (iphdr *)eth_payload;
    ip_payload = ((payload_t)ipHdr) + IPv4_HSIZE;
    ipLength = length - ETH_HSIZE;
  }
  virtual ~IP_Packet() {}
  virtual int chksum();
  bool validate(bool set = false)
  {
    assert(ipHdr != NULL);
    bool retvalue = ((ipHdr->ihl == IPv4_HSIZE >> 2) && (ipHdr->version == IPVERSION));
    if(set) {
      ipHdr->ihl = IPv4_HSIZE >> 2;
      ipHdr->version = IPVERSION;
    }
    return retvalue;
  }
  unsigned long getDAFlowID() 
  {
    return getDstAddr() + getSrcAddr();
  }
  
  // Header getters and setters
  inline unsigned int getIPVersion() const {return ipHdr->version;}
  inline uint8_t getTos() const {return ipHdr->tos;}
  inline void setTos(uint8_t t) {ipHdr->tos = t;}
  inline uint16_t getTotLen() const {return ntohs(ipHdr->tot_len);}
  inline void setTotLen(uint16_t tl) {ipHdr->tot_len = htons(tl);}
  inline uint16_t getId() const {return ntohs(ipHdr->id);}
  inline void setId(uint16_t i) {ipHdr->id = htons(i);}
  inline uint16_t getFragOff() const {return ntohs(ipHdr->frag_off);}
  inline void setFragOff(uint16_t f) {ipHdr->frag_off = htons(f);}
  inline uint8_t getTtl() const {return ipHdr->ttl;}
  inline void setTtl(uint8_t t) {ipHdr->ttl = t;}
  inline uint8_t getProt() const {return ipHdr->protocol;}
  inline void setProt(uint8_t p) {ipHdr->protocol = p;}
  inline uint32_t getSrcAddr () const {return ntohl(ipHdr->saddr);}
  inline void setSrcAddr(uint32_t sa) {ipHdr->saddr = htonl(sa);}
  inline uint32_t getDstAddr() const {return ntohl(ipHdr->daddr);}
  inline void setDstAddr(uint32_t da) {ipHdr->daddr = htonl(da);}
  
};

}

#endif // IP_PACKET_HH
